import { Animation, Asset, Camera, Label, Node, Prefab, ProgressBar, Skeleton, UIComponent, UIRenderer, Vec2, Vec3, dragonBones, instantiate, tween, v2, view } from "cc";
import { resourceManager } from "./ResourceManager";

/**
 * 输出debug信息
 * @param  {string} tag tag
 * @param  {any[]} ...log
 */
export function debugLog(tag: string, ...log: any[]) {
    console.log.call(null, `[DEBUG]: ${tag}`, ...log);
}
/**
 * 休眠一段时间
 * @param  {number} time 休眠时间
 */
export async function sleep(time: number) {
    return new Promise((resolve) => {
        let id = setTimeout(() => {
            clearTimeout(id);
            resolve(null);
        }, time);
    })
}

/**
 * 产生 [min,max - 1]之间的随机数
 * @param  {number} min
 * @param  {number} max
 * @returns number
 */
export function createRandom(min: number, max: number): number {
    return Math.floor(Math.random() * (max - min) + min);
}

/**
 * 向着目标产生随机数：目标值的随机数概率很大
 * @param  {number} min
 * @param  {number} max
 * @param  {number} wantNumber 目标值
 */
export function createRandomTowardTarget(min: number, max: number, wantNumber: number) {
    const random = Math.floor(Math.random() * (max - min) * 100 + min * 100);

    if (random > (min * 100) && random < (max - 2) * 100) {
        return wantNumber;
    } else {
        return Math.floor(random / 100);
    }
}

/**
 * 等待动画播放完毕
 * @param  {cc.Node} node 想要播放动画的节点
 * @param  {string} animationName 动画名称
 * @param  {boolean} isReverse 是否倒序播放
 */
// export async function waitAnimOver(
//     node: Node,
//     animationName: string,
//     isReverse: boolean = false
// ) {
//     if (!node) {
//         console.warn("node is null");
//         return;
//     }
//     const animCom = node.getComponent(Animation);
//     if (animCom) {
//         return new Promise((resolve) => {
//             const animState = animCom.play(animationName);
//             if (isReverse) {

//                 animState.wrapMode = WrapMode.Reverse;
//             } else {
//                 animState.wrapMode = cc.WrapMode.Normal;
//             }
//             animCom.once("finished", resolve);
//         });
//     } else {
//         console.warn("node's animation is null,please add animation component");
//     }
// }

/**
 * 循环播放一个动画
 * @param  {cc.Node} node 动画所在的节点
 * @param  {string} animationName 动画名
 */
export function loopAnimation(node: Node, animationName: string) {
    if (node) {
        const animCom = node.getComponent(Animation);
        if (animCom) {
            const state = animCom.play(animationName);
            // state.wrapMode = cc.WrapMode.Loop;
        }
    }
}

/**
 * 停止当前节点正在播放的动画
 * @param  {cc.Node} node
 */
export function stopCurAnimation(node: Node) {
    if (node) {
        const animComp = node.getComponent(Animation);
        if (!animComp) return;
        animComp.stop();
    }
}

/**
 * @param  {cc.Node} node 播放动画的节点
 * @param  {number} clipIndex clip在animation中的索引
 */
export async function waitAnimOverByIndex(node: Node, clipIndex: number) {
    if (!node) {
        console.warn("node is null");
        return;
    }
    const animCom = node.getComponent(Animation);
    const clips = animCom.clips;
    if (animCom) {
        return new Promise((resolve) => {
            animCom.play(clips[clipIndex].name);
            // @ts-ignore
            animCom.once("finished", resolve);
        });
    } else {
        console.warn("node's animation is null,please add animation component");
    }
}

/**
* @param  {sp.Skeleton} sp 骨骼动画组件
* @param  {string} fromAnimation 从哪个动画过渡到目标动画
* @param  {string} toAnimation 目标动画
* @param  {number} delay 过渡时长 默认0.2秒 过度到目标动画循环播放
*/
export function smoothTransitionSpAnimation(
    sp: Skeleton,
    fromAnimation: string,
    toAnimation: string,
    delay: number = 0.5,
    isLoop: boolean = true
) {
    /** 过渡到目标动画循环播放 */
    // sp.loop = isLoop;
    // sp.setMix(fromAnimation, toAnimation, delay);
    // sp.animation = toAnimation;

    // return new Promise((resolve) => {
    //     sp.setCompleteListener(resolve);
    // });
}

/**
 * 播放龙骨动画
 * @param  {dragonBones.ArmatureDisplay} dragonbone 龙骨组件
 * @param  {string} animationName 动画名称
 * @param  {number=1} playTime 播放次数 默认1次 0：无限循环 >0：播放指定的次数
 */
export async function playDragonBonesAnim(dragonbone: dragonBones.ArmatureDisplay, animationName: string, playTime: number = 1) {
    if (playTime === 0) {
        dragonbone.playAnimation(animationName, playTime);
    } else {
        dragonbone.playAnimation(animationName, playTime);
        return new Promise((resolve) => {
            // dragonbone.addEventListener(dragonBones.EventObject.COMPLETE, () => {
            //     dragonbone.removeEventListener(dragonBones.EventObject.COMPLETE);
            //     resolve(null);
            // });
        });
    }
}

/**
 * 预加载bundle里面的资源
 * @param  {string} url bundle里面的路径
 * @param  {typeofcc.Asset} type 资源类型
 * @param  {string='resources'} bundleName bundle名字
 * @returns Promise
 */
export async function preloadAssetInBundle<T extends Asset>(url: string, type: typeof Asset, bundleName: string = 'resources'): Promise<T> {
    if (!url) return;

    // let bundle = null;
    // bundle = await resourceManager.loadBundle(bundleName);
    // if(!bundle) return;
    const res = await resourceManager.loadAssetInBundle<T>(url, type, bundleName) as T;
    if (!res) return;
    return res;
}

/**
 * 根据传入进来的r和x计算y坐标
 * @param  {number} x 圆上的一个随机点
 * @param  {number} r 圆半径
 * @param  {number} x0 圆心坐标x
 * @param  {number} y0 圆心坐标y
 * @returns number
 */
export function getYInCircleByRandomX(x: number, r: number, x0: number = 0, y0: number = 0): number {
    // 圆方程 (x - x0)^2 + (y - y0)^2 = r^2
    let ysubY02 = Math.pow(r, 2) - Math.pow(x - x0, 2);
    if (ysubY02 < 0) ysubY02 = 0;
    return Math.sqrt(ysubY02) + y0;
}

/**
 * 围绕圆心坐标旋转指定的点和角度
 * @param  {cc.Vec2} rotatePoint 需要旋转的点
 * @param  {cc.Vec2} centerPoint 旋转中心
 * @param  {number} angle 旋转的角度 弧度值
 * @returns cc.Vec2 旋转后的点
 */
export function rotateByPoint(rotatePoint: Vec2, centerPoint: Vec2, angle: number): Vec2 {
    const x = (rotatePoint.x - centerPoint.x) * Math.cos(angle) - (rotatePoint.y - centerPoint.y) * Math.sin(angle) + centerPoint.x;
    const y = (rotatePoint.x - centerPoint.x) * Math.sin(angle) + (rotatePoint.y - centerPoint.y) * Math.cos(angle) + centerPoint.y;
    return v2(x, y);
}

/**
 * 根据name获取url中的参数
 * @param  {string} name 参数名
 */
export function getUrlParameterValue(name) {
    let href = window.location.href;
    var query = href.substring(1);
    var vars = query.split("?");
    if (!vars[1]) {
        return '';
    }
    var argment = vars[1].split("&");;
    for (var i = 0; i < argment.length; i++) {
        var pair = argment[i].split("=");
        if (pair[0] == name) { return pair[1]; }
    }
    return '';
}

/**
 * 检测一个数是否在指定的范围内
 * @param  {number} target 指定的数
 * @param  {number} min 指定的方位的最小值
 * @param  {number} max 指定的范围的最大值
 * @returns boolean
 */
export function numberIsInRange(target: number, min: number, max: number): boolean {
    return target >= min && target <= max;
}

/** 判断一个数是否是整数 */
export function isInteger(num: number): boolean {
    return typeof num === 'number' && num % 1 === 0;
}

/**
 * 洗牌简单算法
 * @param  {any[]} arr 需要洗牌的数组
 */
export function shuffle(arr: any[]) {
    const swap = (index1: any, index2: any) => {
        const temp = arr[index1];
        arr[index1] = arr[index2];
        arr[index2] = temp;
    }
    const n = arr.length;
    for (let i = 0; i < n; i++) {
        // 获得一个随机位置
        let rand = Math.floor((Math.random() * 101)) % (n - i);
        //交换两个位置的数据
        swap(i, rand);
    }
}

/**
 * 为一个字符串添加省略号
 * @param  {string} str 字符串
 * @param  {number} targetLen 多少文字长度以后添加省略号
 * @returns void
 */
export function usernameSlice(str: string, targetLen: number): string {
    if (str.length <= targetLen) return str;
    if (str.length > targetLen) return str.substr(0, targetLen) + '..';

}

/**
 * 对label中的数字进行tween变换
 * @param  {number} curVal
 * @param  {number} targetVal
 * @param  {cc.Label} label 文本组件
 * @param  {number} time 变换数字文本的时间
 * @returns Promise
 */
export async function tweenLabelString(curVal: number, targetVal: number, label: Label, time: number = 1): Promise<void> {
    let obj = { value: curVal }
    return new Promise((resolve) => {
        tween(obj).to(time, { value: targetVal }, {
            easing: 'cubicOut', progress: (start, end, current, ratio) => {
                const res = Math.floor(start + (end - start) * ratio);
                label.string = res.toString();
                return res;
            }
        }).call(resolve).start();
    })
}

/**
 * 对label中的数字进行tween变换
 * @param  {cc.Prefab} particle 进度粒子
 * @param  {number} targetVal 目标进度值
 * @param  {cc.ProgressBar} progressBar 进度条组件
 * @returns Promise
 */
export async function tweenProgress(particle: Prefab, targetVal: number, progressBar: ProgressBar): Promise<void> {
    // const barNode = progressBar.barSprite.node;
    // const partNode = instantiate(particle);
    // partNode.parent = barNode;

    // tween(progressBar).to(1, { progress: targetVal }, {
    //     easing: 'cubicOut', progress: (start, end, cur, ratio) => {
    //         const res = start + (end - start) * ratio;
    //         partNode.position.x = res * progressBar.node.width;
    //         return res;
    //     }
    // }).start();
}

export function utcToGmt(UTCDateString) {
    if (!UTCDateString) {
        return '-';
    }
    function formatFunc(str) {    //格式化显示
        return str > 9 ? str : '0' + str
    }
    var date2 = new Date(UTCDateString);
    var year = date2.getFullYear();
    var mon = formatFunc(date2.getMonth() + 1);
    var day = formatFunc(date2.getDate());
    var hour = date2.getHours();
    var noon = hour >= 12 ? 'PM' : 'AM';
    hour = hour >= 12 ? hour - 12 : hour;
    hour = formatFunc(hour);
    var min = formatFunc(date2.getMinutes());
    var dateStr = year + '-' + mon + '-' + day + ' ' + noon + ' ' + hour + ':' + min;
    return dateStr;
}

export function abs(a: number) {
    return (a ^ (a >> 31)) - (a >> 31);
}

/**
 * 弧度转角度
 * @param  {number} rad
 */
export function randToAngle(rad: number) {
    return rad * 180 / Math.PI;
}

/**
 * 角度转弧度
 * @param  {number} angle
 */
export function angleToRand(angle: number) {
    return angle * Math.PI / 180;
}

/**
 * 将摄像机的垂直视角转换为水平视角
 * @param  {Camera} camera
 */
export function vFovToHFov(camera: Camera) {
    const halfFov = camera.fov / 2;
    const tanHalfFov = Math.tan(angleToRand(halfFov));
    const scale = view.getVisibleSize().width / view.getVisibleSize().height;

    const targetTan = tanHalfFov * scale;
    const targetRad = Math.atan(targetTan);
    const targetAngle = randToAngle(targetRad);
    return targetAngle * 2;
}

/**
 * 将摄像机的水平视角转换为垂直视角
 * @param  {Camera} camera
 */
export function hFovToVFov(camera: Camera) {

    const halfFov = camera.fov / 2;
    const tanHalfFov = Math.tan(angleToRand(halfFov));
    const scale = view.getVisibleSize().height / view.getVisibleSize().width;

    const targetTan = tanHalfFov * scale;
    const targetRad = Math.atan(targetTan);
    const targetAngle = randToAngle(targetRad);
    return targetAngle * 2;
}

/**
 * 是否是生产环境
 */
export function isProd() {
    return window.location.href.indexOf('prod') >= 0 ? true : false;
}

export function sameElement(arr1: Array<any>, arr2: Array<any>) {
    if (arr1.length != arr2.length) return false;
    return arr1.every(it => arr2.indexOf(it) >= 0);
}

export function formatTime(timeNUmber) {
    timeNUmber = String(timeNUmber).length == 10 ? timeNUmber * 1000 : timeNUmber;
    let date = new Date(timeNUmber);
    let year = date.getFullYear();
    let month = date.getMonth() + 1;
    let day = date.getDate();
    let hourse = date.getHours();
    let min = date.getMinutes();
    let _month = month < 10 ? `0${month}` : month;
    let _day = day < 10 ? `0${day}` : day;
    let _hourse = hourse < 10 ? `0${hourse}` : hourse;
    let _min = min < 10 ? `0${min}` : min;
    return `${_hourse}:${_min}`;
}

/**
 * 
 * 检查一个二维数组里面是否有连成线的节点,并且返回这些线 迭代算法
 * @param  {number[][]} arr
 */
export const lineCheck = (arr: number[][]) => {
    const len = arr.length;
    let aLen = len;

    const searchRes = [];
    /**
     * 各个方向进行搜索
     * @param  {number} row 行
     * @param  {number} col 列
     * @param  {number} i 方向
     * @param  {[key: string]: number}[] list 每个方向搜索的结果
     */
    const dirCheck = (row: number, col: number, i: number, list: number[]) => {
        let tempRow = row;
        let tempCol = col;

        let res = [];
        // 当前行列push进去
        if (arr[row][col] > 0) {
            let keys = `${tempRow},${tempCol}`;
            let obj = {};
            obj[keys] = arr[tempRow][tempCol];
            res.push(obj);
        }

        while (tempRow >= 0 || tempRow <= aLen - 1 || tempCol >= 0 || tempCol <= aLen - 1) {
            switch (i) {
                case 0:
                    // 0度方向
                    tempCol++;
                    break;
                case 1:
                    // 45度方向
                    tempCol++;
                    tempRow--;
                    break;
                case 2:
                    // 90度方向
                    tempRow--;
                    break;
                case 3:
                    // 135度方向
                    tempRow--;
                    tempCol--;
                    break;

            }
            if (tempRow < 0 || tempRow > aLen - 1 || tempCol < 0 || tempCol > aLen - 1) {
                // 超出边界
                break;
            }

            // 边界内检测
            if (arr[tempRow][tempCol] > 0) {
                let keys = `${tempRow},${tempCol}`;
                let obj = {};
                obj[keys] = arr[tempRow][tempCol];
                res.push(obj);
            } else {
                break;
            }
        }

        tempRow = row;
        tempCol = col;

        while (tempRow >= 0 || tempRow <= aLen - 1 || tempCol >= 0 || tempCol <= aLen - 1) {
            switch (i) {
                case 0:
                    // 180度方向
                    tempCol--;
                    break;
                case 1:
                    // 225度方向
                    tempRow++;
                    tempCol--;
                    break;
                case 2:
                    // 270度方向
                    tempRow++;
                    break;
                case 3:
                    // 315度方向
                    tempRow++;
                    tempCol++;
                    break;
            }
            if (tempRow < 0 || tempRow > aLen - 1 || tempCol < 0 || tempCol > aLen - 1) {
                // 超出边界
                break;
            }
            // 边界内检测
            if (arr[tempRow][tempCol] > 0) {
                let keys = `${tempRow},${tempCol}`;
                let obj = {};
                obj[keys] = arr[tempRow][tempCol];
                res.push(obj);

            } else {
                break;
            }
        }

        if (res.length >= aLen) {
            // 连成了线
            list.push(...res);
        }

    }

    /**
     * 迭代方式搜索
     */
    const iteraSearch = (row: number, col: number) => {
        let t = [];
        for (let i = 0; i < 4; i++) {
            let res = [];
            // 八个方向检测
            dirCheck(row, col, i, res);
            if (res.length >= aLen) {
                // 将搜索结果保存
                t.push(res);
            }
        }
        // 汇总搜索结果
        searchRes.push(t);
    }


    for (let i = 0; i < len; i++) {
        for (let j = 0; j < len; j++) {
            if (!i || !j) {
                // 优化为只有数组的上边界和左边界才会进行搜索算法
                iteraSearch(i, j);
            }
        }
    }

    let deleteIndexs = [];
    let total = [];
    for (let i = 0; i < searchRes.length; i++) {
        let searchItems = searchRes[i];
        if (!searchItems.length) continue;
        for (let j = 0; j < searchItems.length; j++) {
            const keys = searchItems[j].map(item => Object.keys(item)[0]);
            total.push(searchItems[j]);
        }
    }

    for (let i = 0; i < total.length; i++) {
        if (deleteIndexs.indexOf(i) >= 0) continue;
        const keys = total[i].map(it => Object.keys(it)[0]);

        for (let j = 0; j < total.length; j++) {
            if (i == j) continue;
            const ikeys = total[j].map(item => Object.keys(item)[0]);
            if (sameElement(ikeys, keys)) {
                if (!(deleteIndexs.indexOf(j) >= 0)) {
                    deleteIndexs.push(j);
                }
            }
        }
    }
    let realTotal = total.reduce((pre, cur, index) => {
        if (!(deleteIndexs.indexOf(index) >= 0)) {
            pre.push(cur);
        }
        return pre;
    }, []);
    return realTotal;
}

export const replaceTplVar = (str, arr) => {
    if (!str) return '';
    const tpls = str.match(/\$\d+\%\w/g);
    if (!tpls) {
        console.log('tpls is null', str, arr);
        return str;
    }
    if (tpls.length != arr.length) {
        return 'LESS VAL';
    }
    for (let i = 0; i < tpls.length; i++) {
        str = str.replace(tpls[i], arr[i]);
    }
    return str;
}

export const replaceTplVar2 = (str, arr) => {
    if (!str) return '';
    const tpls = str.match(/\%\d+\$\w/g);
    if (!tpls) {
        console.log('tpls is null', str, arr);
        return str;
    }
    if (tpls.length != arr.length) {
        return 'LESS VAL';
    }
    for (let i = 0; i < tpls.length; i++) {
        str = str.replace(tpls[i], arr[i]);
    }
    return str;
}

/**
 * 找出两个数组的不同选项
 * @param  {number[]} best 数组1
 * @param  {number[]} self 数组2
 */
export function findDiff(best: number[], self: number[]) {
    let res = [];
    best.forEach((item, index) => {
        if (self.indexOf(item) < 0) {
            res.push(index);
        }
    });
    return res
}

export function splitVersionNum(version: number) {
    if (version > 9999) version = 9999;
    let versionStr = version.toString();
    let vs = versionStr.split('').join(".");
    return vs;
}

export function deepClone(obj) {
    let newObj = obj instanceof Array ? [] : {};
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key];
        }
    }
    return newObj;
}


/**
 * 播放从大到小的缩放（同时改变透明度）
 * @param  {cc.Node} node
 * @param  {number=1} time
 */
export async function playVsLikeAnimation(node: Node, time: number = 1): Promise<void> {
    const t = tween;
    node.scale = new Vec3(4, 4, 4);
    // node.scale = 4.0;
    const uiRender = node.getComponent(UIRenderer);
    // uiRender.color = new Color(255, 255, 255, 0);
    // uiRender.
    // node.opacity = 0;
    return new Promise((resolve, reject) => {
        t(node).parallel(
            t().to(time, { scale: 1 }, { easing: 'backInOut' }),
            t().to(time, { opacity: 255 }, { easing: 'backInOut' })
        ).call(resolve).start();
    });
}

/**
 * 寻找数组中3个相同的连续数字
 * @param  {T[]} nodes
 * @returns number[] 返回三个连续数字的索引开始和结束位置
 */
export function findThreeCommon<T>(nodes: T[], pro: string): { deleted: T[], indexs: number[] } {
    let newName = null;

    const res = {
        deleted: [],
        indexs: []
    };
    let deleteArray = [];
    let resIndex: number[] = [];

    let commonCount = 0;
    let commonStart = 0;

    for (let i = 0; i < nodes.length; i++) {
        if (nodes[i][pro] != newName) {
            newName = nodes[i][pro];
            commonCount = 0;
            commonStart = i;
        } else {
            // 新数和当前的数相同
            commonCount++;
            if (commonCount >= 2) {
                deleteArray = nodes.splice(commonStart, 3);
                resIndex.push(commonStart, i);
                res.deleted = deleteArray;
                res.indexs = resIndex;
                break;
            }
        }
    }
    return res;
}

/**
 * 寻找数组中n个相同的连续数字 不删除原数组只返回需要删除的索引数组
 * @param  {T[]} nodes
 * @returns number[] 返回三个连续数字的索引开始和结束位置
 */
export function findNCommon<T>(nodes: T[], pro: string, n: number): number[] {
    let newName = null;

    let resIndex: number[] = [];

    let commonCount = 0;
    let commonStart = 0;

    for (let i = 0; i < nodes.length; i++) {
        if (nodes[i][pro] != newName) {
            newName = nodes[i][pro];
            commonCount = 0;
            commonStart = i;
        } else {
            // 新数和当前的数相同
            commonCount++;
            if (commonCount >= n - 1) {
                for (let c = commonStart; c <= i; c++) {
                    resIndex.push(c);
                }
                break;
            }
        }
    }
    return resIndex;
}

/**
 * 分组相同元素
 * @param  {Array<number>} arr
 */
export function groupSameElements(arr: number[]) {
    for (let i = 0; i < arr.length; i++) {
        let element = arr[i];
        // 从当前元素的下一个元素开始搜索相同元素
        for (let j = i + 1; j < arr.length; j++) {
            if (arr[j] === element && j - i > 1) {
                // 发现相同元素，将其移至i的右侧
                let temp = arr[j];
                // 将中间的元素向右移动
                for (let k = j; k > i + 1; k--) {
                    arr[k] = arr[k - 1];
                }
                // 将找到的相同元素放到i的右侧
                arr[i + 1] = temp;
                // 调整i的位置，因为我们已经处理了i+1位置的元素
                i++;
            }
        }
    }
    return arr;
}

/**
 * 分组相同元素 更高效的方式 多占用内存空间,返回变化的索引位置，和最终的结果
 * @param  {any[]} arr
 * @returns {result: any[] indexChanges: string[]}
 */
export function groupSameElements2(arr: any[], targetNode: Node, pro: string) {
    // 第一步：记录每个元素出现的所有位置
    const elementIndices = {};
    arr.forEach((element, index) => {
        const key = pro ? element[pro] : element;
        if (!elementIndices.hasOwnProperty(key)) {
            elementIndices[key] = [];
        }
        elementIndices[key].push(index);
    });

    // 准备记录索引变化
    const indexChanges = [];

    // 第二步：构建最终数组并记录索引变化
    const result = [];
    const processed = new Set(); // 跟踪已处理元素
    let newIndex = 0; // 跟踪在新数组中的位置
    let insertPos = -1;

    for (let i = 0; i < arr.length; i++) {
        if (arr[i] != targetNode && arr[i][pro] == targetNode[pro]) {
            insertPos = i + 1;
        }
    }

    arr.forEach(element => {
        const key = pro ? element[pro] : element;
        if (!processed.has(key)) {
            processed.add(key);
            // 添加所有相同的元素到结果数组，并记录索引变化
            elementIndices[key].forEach(originalIndex => {
                result.push(arr[originalIndex]);
                if (newIndex > insertPos && originalIndex != newIndex) {

                    indexChanges.push(`${originalIndex} -> ${newIndex}`);
                }
                newIndex++;
            });
        }
    });

    // 返回结果数组和索引变化记录
    return { result, indexChanges, insertPos };
}

/**
 * 
 * 队列js实现
 * 
 */
export class Queue<T> {
    private items: T[] = [];

    constructor() {
        this.items = [];
    }

    /**
     * 向队尾插入一个元素
     * @param  {any} item
     */
    push(item: T) {
        this.items.push(item);
    }

    /** 向队首插入一个元素 */
    unShift(item: T) {
        this.items.unshift(item);
    }


    /**
     * 从队首弹出一个元素
     */
    pop(): T {
        if (this.isEmpty()) {
            return null;
        }
        return this.items.shift();
    }

    // 检查队列是否为空
    isEmpty() {
        return this.items.length === 0;
    }


    /**
     * 查看队首的元素
     */
    peek(): T {
        if (this.isEmpty()) {
            return null;
        }
        return this.items[0];
    }

    getItemByIndex(index: number): T {
        if (this.isEmpty()) {
            return null;
        }
        return this.items[index];
    }

    // 获取队列长度
    size() {
        return this.items.length;
    }

    // 清空队列
    clear() {
        this.items.length = 0;
    }
}

/**
 * 节流函数
 * @param  {} func
 * @param  {} delay
 */
export function throttle(func, delay) {
    let timer;
    return function () {
        const context = this;
        const args = arguments;
        if (!timer) {
            timer = setTimeout(() => {
                func.apply(context, args);
                timer = null;
            }, delay);
        }
    }
}

// export function deleteEle

